package freaks.terah.model;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;

import javax.swing.DefaultComboBoxModel;
import javax.swing.ListCellRenderer;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class PlayerModel {
	private RessourceModel ownedStructures;
	private RessourceModel newStructures;
	private RessourceModel buildableStructures;
	private RessourceModel salvagedStructures;
	
	private RessourceModel ownedTechs;
	private RessourceModel newTechs;
	private RessourceModel researchTechs;
	private RessourceModel integrateTechs;
	
	private RessourceModel newUnits;
	private RessourceModel ownedUnits;
	private RessourceModel buildableUnits;
	private RessourceModel destroyedUnits;
	
	private DefaultComboBoxModel shipList;
	private DefaultComboBoxModel soldierList;
	private DefaultComboBoxModel technicianList;
	
	private int goal;
	private int ship;
	private int playerNumber;
	private int role;
	
	private APListRenderer listAPRenderer;
	private RessourceListRenderer listRenderer;
	
	private ArrayList<Observer> listeners;
	
	public final int ACTION_RESEARCH_TECH = 0;
	public final int ACTION_INTEGRATE_TECH = 1;
	public final int ACTION_CANCEL_RESEARCH_TECH = 2;
	public final int ACTION_CANCEL_INTEGRATE_TECH = 3;
	public final int ACTION_CREATE_UNIT = 4;
	public final int ACTION_SALVAGE_UNIT = 5;
	public final int ACTION_CANCEL_CREATE_UNIT = 6;
	public final int ACTION_CANCEL_SALVAGE_UNIT = 7;
	public final int ACTION_CREATE_STRUCTURE = 8;
	public final int ACTION_SALVAGE_STRUCTURE = 9;
	public final int ACTION_CANCEL_CREATE_STRUCTURE = 10;
	public final int ACTION_CANCEL_SALVAGE_STRUCTURE = 11;
	public final int ACTION_ACTIVATE_STRUCTURE = 12;
	public final int ACTION_DESACTIVATE_STRUCTURE = 13;
	
	private int[] myRessources = {5,5,5,5,5,5,5,5,5};
	private int currentAP = 2;
	
	public int getCurrentAP() {
		return currentAP;
	}
	
	public void setCurrentAP(int i) {
		currentAP = 2;
	}
	
	public void setRole(int aRole)
	{
		role = aRole;
	}
	
	public int getRole() {
		return role;
	}
	
	public void setGoal(int goal) {
		this.goal = goal;
	}

	public int getGoal() {
		return goal;
	}

	public void setPlayerNumber(int playerNumber) {
		this.playerNumber = playerNumber;
	}

	public int getPlayerNumber() {
		return playerNumber;
	}
	
	public void setShip(int ship) {
		this.ship = ship;
	}

	public int getShip() {
		return ship;
	}

	private HashMap<String, Ressource> templates;
	private ArrayList<Ressource> numberTemplates = new ArrayList<Ressource>();
	private ArrayList<Ressource> ownedRessources = new ArrayList<Ressource>();
	
	public PlayerModel(int aGoal, int aShip, int aPlayerNumber, int aRole) {
		listAPRenderer = new APListRenderer(this);
		listRenderer = new RessourceListRenderer();
		listeners = new ArrayList<Observer>();
		setRole(aGoal);
		setShip(aShip);
		setPlayerNumber(aPlayerNumber);
		setRole(aRole);
		try {
			InputStream is = getClass().getClassLoader().getResourceAsStream("template.xml");
			//File fXmlFile = new File(is);
			DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
			dbFactory.setIgnoringElementContentWhitespace(true);
			DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
			Document doc = dBuilder.parse(is);
			doc.getDocumentElement().normalize();

			System.out.println("Parsing XML data");
			NodeList nList = doc.getElementsByTagName("templates");
			System.out.println("-----------------------");
			templates = new HashMap<String, Ressource>();
			numberTemplates.add(null);
			int templatesLength = 0;
			for (int temp = 0; temp < nList.getLength(); temp++) {
				Node templatesNode = nList.item(temp);
				NodeList templateList = templatesNode.getChildNodes();
				for (int templateIndex = 0; templateIndex < templateList.getLength(); templateIndex++) {
					Node template = templateList.item(templateIndex);
					if (template.getNodeName() == "template")
					{
						template.getAttributes().getNamedItem("id").getNodeValue();
						Node id = template.getAttributes().getNamedItem("id");
						if (id == null)
						{
							System.out.println("ERROR: Template Node #" + templateIndex + " is missing an ID!");
						}
						else {
							templatesLength++;
							Ressource newRessource = this.parseXMLTemplate(template, templatesLength);
							numberTemplates.add(newRessource);
							if (newRessource != null)
							{
								templates.put(id.getNodeValue(), newRessource);
							}
							System.out.println("Added template id: " + id.getNodeValue());
						}
					}
				}
			}

			/*NodeList randomList = doc.getElementsByTagName("randomset");

			for (int randomIndex = 0; randomIndex < randomList.getLength(); randomIndex++)
			{
				Node randomSet = randomList.item(randomIndex);
				String name = getAttributeString(randomSet, "name");
				int diceSize = getAttributeInt(randomSet, "diceSize");
				int diceNb = getAttributeInt(randomSet, "diceNum");

				RandomSet rdSet = new RandomSet(diceNb, diceSize);

				NodeList randomValues = randomSet.getChildNodes();

				for (int valueIndex = 0; valueIndex < randomValues.getLength(); valueIndex++)
				{
					Node randomValue = randomValues.item(valueIndex);

					if (randomValue.getNodeName() != "value")
						continue;

					int min = getAttributeInt(randomValue, "minValue");
					int max = getAttributeInt(randomValue, "maxValue");
					String value = getAttributeString(randomValue, "value");


					rdSet.setValue(value, min, max);
				}

				randomMap.put(name, rdSet);
			}*/
		} catch (Exception e) {
			e.printStackTrace();
		}

		ownedStructures = new RessourceModel();
		newStructures = new RessourceModel();
		buildableStructures = new RessourceModel();
		salvagedStructures = new RessourceModel();
		
		ownedTechs = new RessourceModel();
		newTechs = new RessourceModel();
		researchTechs = new RessourceModel();
		integrateTechs = new RessourceModel();
		
		newUnits = new RessourceModel();
		ownedUnits = new RessourceModel();
		buildableUnits = new RessourceModel();
		destroyedUnits = new RessourceModel();
		
		shipList = new DefaultComboBoxModel();
		soldierList = new DefaultComboBoxModel();
		technicianList = new DefaultComboBoxModel();
		
		initData();
	}
	
	public RessourceModel getOwnedStructures()
	{
		return ownedStructures;
	}
	public RessourceModel getNewStructures()
	{
		return newStructures;
	}
	
	public RessourceModel getBuildableStructures()
	{
		return buildableStructures;
	}
	
	public RessourceModel getSalvagedStructures()
	{
		return salvagedStructures;
	}
	
	public RessourceModel getOwnedTechs()
	{
		return ownedTechs;
	}
	
	public RessourceModel getNewTechs()
	{
		return newTechs;
	}
	
	public RessourceModel getResearchTechs()
	{
		return researchTechs;
	}
	
	public RessourceModel getIntegrateTechs()
	{
		return integrateTechs;
	}
	
	public RessourceModel getNewUnits()
	{
		return newUnits;
	}
	
	public RessourceModel getDestroyedUnits()
	{
		return destroyedUnits;
	}
	
	public RessourceModel getBuildableUnits()
	{
		return buildableUnits;
	}
	
	public RessourceModel getOwnedUnits()
	{
		return ownedUnits;
	}
	
	public DefaultComboBoxModel getShipList()
	{
		return shipList;
	}
	
	public DefaultComboBoxModel getSoldierList()
	{
		return soldierList;
	}
	
	public DefaultComboBoxModel getTechnicianList()
	{
		return technicianList;
	}
	
	private void initData()
	{
		//TEMPLATE LOADING
		for (Entry<String, Ressource> entry : templates.entrySet())
		{
			if (entry.getValue().getClass() == Structure.class)
			{
				buildableStructures.addElement(entry.getValue());
			}
			
			if (entry.getValue().getClass() == Unit.class)
			{
				buildableUnits.addElement(entry.getValue());
			}
			
			if (entry.getValue().getClass() == Tech.class)
			{
				Tech t = (Tech) entry.getValue();
				if (t.getOrigin() == 0)
				    researchTechs.addElement(entry.getValue());
			}
		}
		
		update();
	}
	
	public void update()
	{
	    updateCombosLists(shipList, "ship");
		updateCombosLists(soldierList, "soldier");
		updateCombosLists(technicianList, "technician");
		
		createFilter(researchTechs);
		createFilter(buildableUnits);
		createFilter(buildableStructures);
		
		notifyObservers();
	}
	
	private void updateCombosLists(DefaultComboBoxModel modelList, String category)
	{
		modelList.removeAllElements();
		for (int i = 0; i < ownedUnits.size();i++)
		{
			if (((Ressource) ownedUnits.get(i)).getCategory().equalsIgnoreCase(category))
			{
				modelList.addElement(ownedUnits.get(i));
			}
		}
		
		for (int i = 0; i < newUnits.size();i++)
		{
			if (((Ressource) newUnits.get(i)).getCategory().equalsIgnoreCase(category))
			{
				modelList.addElement(newUnits.get(i));
			}
		}
	}
	
	public boolean canBuy(Ressource r)
	{
		for (int index = 0; index < 9; index++)
		{
			if (myRessources[index] < r.getCost()[index])
			{
				return false;
			}
		}
		
		if (getCurrentAP() < r.getEditCost())
			return false;
		
		return true;
	}
	
	private void createFilter(RessourceModel modelList)
	{
		modelList.removeFilter();
		ArrayList<Integer> filter = new ArrayList<Integer>();
		for (int i = 0; i < modelList.size();i++)
		{
			Ressource model = (Ressource) modelList.getElementAt(i);

			boolean canBuy = true;

			for (int index = 0; index < model.getPre().size(); index++)
			{
				boolean isContained = false;

				for (int indexOwned = 0; indexOwned < ownedRessources.size(); indexOwned++)
				{
					if (ownedRessources.get(indexOwned).getStringId().equalsIgnoreCase(model.getPre().get(index)))
					{
						isContained = true;
						break;
					}
				}

				if (!isContained)
				{
					canBuy = false;
					break;
				}
			}
			
			for (int index = 0; index < ownedRessources.size(); index++)
			{
			    if (ownedRessources.get(index).getStringId().equalsIgnoreCase(model.getStringId()))
			    	canBuy = false;
			}
			
			if (model.getEditCost() > 2)
				canBuy = false;

			if (canBuy)
				filter.add(new Integer(i));
		}
		
		modelList.setFilter(filter);
	}
	
	public ListCellRenderer getAPRenderer()
	{
		return listAPRenderer;
	}
	
	public ListCellRenderer getRessourceRenderer()
	{
		return listRenderer;
	}
	
	public void doAction(int action, Structure selectedStructure) {
		switch (action) {
		case ACTION_ACTIVATE_STRUCTURE:
			selectedStructure.setActive(true);
			break;
		case ACTION_DESACTIVATE_STRUCTURE:
			selectedStructure.setActive(false);
			break;
		}
		
        update();
		
		notifyObservers();
	}
	
	public void doAction(int action, int selectedIndex) {
		Ressource affectedRessource;

		switch (action) {
		case ACTION_RESEARCH_TECH:
			affectedRessource = (Ressource) researchTechs.getElementAt(selectedIndex);
			researchTechs.removeFilter();
			researchTechs.removeElement(affectedRessource);
			newTechs.addElement(affectedRessource);
			currentAP -= affectedRessource.getEditCost();
            ownedRessources.add(affectedRessource);
			buy(affectedRessource);
			break;
		case ACTION_INTEGRATE_TECH:
			affectedRessource = (Ressource) integrateTechs.getElementAt(selectedIndex);
			integrateTechs.removeElement(affectedRessource);
			newTechs.addElement(affectedRessource);
			currentAP -= affectedRessource.getEditCost();
			ownedRessources.add(affectedRessource);
			break;
		case ACTION_CANCEL_RESEARCH_TECH:
			affectedRessource = (Ressource) newTechs.getElementAt(selectedIndex);
			newTechs.removeElement(affectedRessource);
			researchTechs.addElement(affectedRessource);
			currentAP += affectedRessource.getEditCost();
			sell(affectedRessource);
			ownedRessources.remove(affectedRessource);
			break;
		case ACTION_CANCEL_INTEGRATE_TECH:
			affectedRessource = (Ressource) newTechs.getElementAt(selectedIndex);
			newTechs.removeElement(affectedRessource);
			integrateTechs.addElement(affectedRessource);
			currentAP += affectedRessource.getEditCost();
			ownedRessources.remove(affectedRessource);
			break;
		case ACTION_CREATE_UNIT:
			affectedRessource = (Ressource) buildableUnits.getElementAt(selectedIndex);
			buildableUnits.removeFilter();
			buildableUnits.removeElement(affectedRessource);
			newUnits.addElement(affectedRessource);
			currentAP -= affectedRessource.getEditCost();
			ownedRessources.add(affectedRessource);
			buy(affectedRessource);
			break;
		case ACTION_SALVAGE_UNIT:
			affectedRessource = (Ressource) ownedUnits.getElementAt(selectedIndex);
			ownedUnits.removeElement(affectedRessource);
			destroyedUnits.addElement(affectedRessource);
			ownedRessources.remove(affectedRessource);
			currentAP -= affectedRessource.getEditCost();
			sell(affectedRessource, -1);
			break;
		case ACTION_CANCEL_CREATE_UNIT:
			affectedRessource = (Ressource) newUnits.getElementAt(selectedIndex);
			newUnits.removeElement(affectedRessource);
			buildableUnits.addElement(affectedRessource);
			currentAP += affectedRessource.getEditCost();
			ownedRessources.remove(affectedRessource);
			sell(affectedRessource);
			break;
		case ACTION_CANCEL_SALVAGE_UNIT:
			affectedRessource = (Ressource) destroyedUnits.getElementAt(selectedIndex);
			destroyedUnits.removeElement(affectedRessource);
			ownedUnits.addElement(affectedRessource);
			currentAP += affectedRessource.getEditCost();
			ownedRessources.add(affectedRessource);
			buy(affectedRessource, -1);
			break;
		case ACTION_CREATE_STRUCTURE:
			affectedRessource = (Ressource) buildableStructures.getElementAt(selectedIndex);
			buildableStructures.removeFilter();
			buildableStructures.removeElement(affectedRessource);
			newStructures.addElement(affectedRessource);
			currentAP -= affectedRessource.getEditCost();
			ownedRessources.add(affectedRessource);
			buy(affectedRessource);
			break;
		case ACTION_SALVAGE_STRUCTURE:
			affectedRessource = (Ressource) ownedStructures.getElementAt(selectedIndex);
			ownedStructures.removeElement(affectedRessource);
			salvagedStructures.addElement(affectedRessource);
			currentAP -= affectedRessource.getEditCost();
			ownedRessources.remove(affectedRessource);
			sell(affectedRessource, -1);
			break;
		case ACTION_CANCEL_CREATE_STRUCTURE:
			affectedRessource = (Ressource) newStructures.getElementAt(selectedIndex);
			newStructures.removeElement(affectedRessource);
			buildableStructures.addElement(affectedRessource);
			currentAP += affectedRessource.getEditCost();
			ownedRessources.remove(affectedRessource);
			sell(affectedRessource);
			break;
		case ACTION_CANCEL_SALVAGE_STRUCTURE:
			affectedRessource = (Ressource) salvagedStructures.getElementAt(selectedIndex);
			salvagedStructures.removeElement(affectedRessource);
			ownedStructures.addElement(affectedRessource);
			currentAP += affectedRessource.getEditCost();
			ownedRessources.add(affectedRessource);
			buy(affectedRessource, -1);
			break;
		};
		
		update();
		
		notifyObservers();
	}
	
	private void sell(Ressource affectedRessource) {
		sell(affectedRessource, 0);
	}
	
	private void sell(Ressource affectedRessource, int offset) {
		int[] cost = affectedRessource.getCost();
		if (cost != null)
		for (int i = 0; i < 9; i++)
			myRessources[i] = myRessources[i] + (cost[i] + offset < 0 ? 0 : cost[i] + offset);
	}

	private void buy(Ressource affectedRessource) {
		buy(affectedRessource, 0);
	}
	
	private void buy(Ressource affectedRessource, int offset) {
		int[] cost = affectedRessource.getCost();
		if (cost != null)
		for (int i = 0; i < 9; i++)
			myRessources[i] = myRessources[i] - (cost[i] + offset < 0 ? 0 : cost[i] + offset);
	}

	private Ressource parseXMLTemplate(Node template, int id)
	{
		String idString = getAttributeString(template, "id");
		String type = getAttributeString(template, "type");
		String name = "No Name";
		String description = "No Description";
		String category = "Does it really matter?";
		int editCost = 10;
		int[] cost = {0,0,0,0,0,0,0,0,0};
		int[] output = {0,0,0,0,0,0,0,0,0};
		int[] upkeep = {0,0,0,0,0,0,0,0,0};
		int[] stats = {0,0,0,0,0};
		boolean cannotResearch = false;
		ArrayList<String> pre = new ArrayList<String>();
		NodeList templateProperties = template.getChildNodes();
		for (int i = 0; i < templateProperties.getLength(); i++)
		{
			Node currentProperty = templateProperties.item(i);
			
			if (currentProperty.getNodeName() == "name")
			{
				name = currentProperty.getFirstChild().getNodeValue();
			}
			
			if (currentProperty.getNodeName() == "description")
			{
				description = currentProperty.getFirstChild().getNodeValue();
			}
			
			if (currentProperty.getNodeName() == "category")
			{
				category = currentProperty.getFirstChild().getNodeValue();
			}
			
			if (currentProperty.getNodeName() == "editCost")
			{
			    editCost = Integer.parseInt(currentProperty.getFirstChild().getNodeValue());
			}
			
			if (currentProperty.getNodeName() == "ressources")
			{
				NodeList outputNodes = currentProperty.getChildNodes();
				String resType =  getAttributeString(currentProperty,"name");
				
				if (resType.equalsIgnoreCase("cost") || resType.equalsIgnoreCase("output") || resType.equalsIgnoreCase("upkeep"))
				{
					int[] newValues = new int[9];
					for (int inner = 0; inner < outputNodes.getLength(); inner++)
					{
						Node innerNode = outputNodes.item(inner);
						if (innerNode.getNodeName() == "ressource")
						{
							String templateName = innerNode.getAttributes().getNamedItem("template").getNodeValue();
							if (templateName.equalsIgnoreCase("food"))
							{
								newValues[0] = Integer.parseInt(innerNode.getAttributes().getNamedItem("quantity").getNodeValue());
							} else if (templateName.equalsIgnoreCase("fuel"))
							{
								newValues[1] = Integer.parseInt(innerNode.getAttributes().getNamedItem("quantity").getNodeValue());
							} else if (templateName.equalsIgnoreCase("energy"))
							{
								newValues[2] = Integer.parseInt(innerNode.getAttributes().getNamedItem("quantity").getNodeValue());
							} else if (templateName.equalsIgnoreCase("scrap"))
							{
								newValues[3] = Integer.parseInt(innerNode.getAttributes().getNamedItem("quantity").getNodeValue());
							} else if (templateName.equalsIgnoreCase("machine"))
							{
								newValues[4] = Integer.parseInt(innerNode.getAttributes().getNamedItem("quantity").getNodeValue());
							} else if (templateName.equalsIgnoreCase("crystal"))
							{
								newValues[5] = Integer.parseInt(innerNode.getAttributes().getNamedItem("quantity").getNodeValue());
							} else if (templateName.equalsIgnoreCase("support"))
							{
								newValues[6] = Integer.parseInt(innerNode.getAttributes().getNamedItem("quantity").getNodeValue());
							} else if (templateName.equalsIgnoreCase("military"))
							{
								newValues[7] = Integer.parseInt(innerNode.getAttributes().getNamedItem("quantity").getNodeValue());
							} else if (templateName.equalsIgnoreCase("insight"))
							{
								newValues[8] = Integer.parseInt(innerNode.getAttributes().getNamedItem("quantity").getNodeValue());
							} else {
								pre.add(templateName);
							}
						}
					}
					
					if (resType.equalsIgnoreCase("cost"))
					{
						cost = newValues;
					}
					
					if (resType.equalsIgnoreCase("output"))
					{
						output = newValues;
					}
					
					if (resType.equalsIgnoreCase("upkeep"))
					{
						upkeep = newValues;
					}
						
				}
				
				/*for (int inner = 0; inner < outputNodes.getLength(); inner++)
				{
					Node innerNode = outputNodes.item(inner);
					if (innerNode.getNodeName() == "ressource")
					{
						String templateName = innerNode.getAttributes().getNamedItem("template").getNodeValue();
						String templateQuantity = innerNode.getAttributes().getNamedItem("quantity").getNodeValue();
						
						array.add(new RessourceRef(templateName, templateQuantity));
					}
				}
				
				currentTemplate.setRessourcesRef(name, array);
				
				System.out.println(name + " ");*/
			}
			
			if (currentProperty.getNodeName() == "stats")
			{
				NodeList outputNodes = currentProperty.getChildNodes();

				for (int inner = 0; inner < outputNodes.getLength(); inner++)
				{
					Node innerNode = outputNodes.item(inner);
					if (innerNode.getNodeName() == "stat")
					{
						String statName = innerNode.getAttributes().getNamedItem("name").getNodeValue();
						String templateValue = innerNode.getAttributes().getNamedItem("value").getNodeValue();
						
						if (statName.equalsIgnoreCase("power"))
							stats[0] = Integer.parseInt(templateValue);
						if (statName.equalsIgnoreCase("defense"))
							stats[1] = Integer.parseInt(templateValue);
						if (statName.equalsIgnoreCase("brain"))
							stats[2] = Integer.parseInt(templateValue);
						if (statName.equalsIgnoreCase("carry"))
							stats[3] = Integer.parseInt(templateValue);
						if (statName.equalsIgnoreCase("ressources"))
							stats[4] = Integer.parseInt(templateValue);
						if (statName.equalsIgnoreCase("cannotResearch"))
							cannotResearch = true;
					}
				}

				System.out.println("Stats ");
			}
		}
		
		if (type.equalsIgnoreCase("structure"))
		{
			return new Structure(name, description, idString, id, category, cost, output, upkeep, pre, editCost);
		}
		
		if (type.equalsIgnoreCase("unit"))
		{
			return new Unit(name, description, idString, id, category, cost, output, upkeep, pre, stats, editCost);
		}
		
		if (type.equalsIgnoreCase("technology"))
		{
			return new Tech(name, description, idString, id, category, cost, output, upkeep, pre, cannotResearch == true ? 1 : 0, editCost);
		}
		
		return null;
	}

	/*private int getAttributeInt(Node n, String s)
	{
		String attributeString = getAttributeString(n,s);

		if (attributeString == null)
			return -1;

		try
		{
			return Integer.parseInt(attributeString);
		} catch (NumberFormatException e)
		{
			return -1;
		}
    }*/

	private String getAttributeString(Node n, String s)
	{
		NamedNodeMap nm = n.getAttributes();
		if (nm != null)
		{
			Node stringNode = nm.getNamedItem(s);

			if (stringNode != null)
				return stringNode.getNodeValue();
		}

		return null;
	}
	
	public void doPreTurn()
	{
		// TODO Finish PreTurn stuff.
		
		// Mission returns with ressources, if applicable
		
		update();
	}
	
	public void doPostTurn()
	{
		int[] curRes = getPlayerRessources();
		int[] sUp = getStructureUpkeep();
		int[] uUp = getUnitUpkeep();
		int[] pro = getProduction();
		int[] net = new int[]{0,0,0,0,0,0,0,0,0};
		
		for (int i = 0; i < 9; i++)
		{
			net[i] = curRes[i] - sUp[i] - uUp[i] + pro[i];
			if (net[i] > 10 && i < 6)
				net[i] = 10;
			
			myRessources[i] = net[i];
		}
	}

	public Data[] getAllPlayerRessources() {
		int totalSize = 9 + ( ownedStructures.getSize() + newStructures.getSize()) * 2 + 
                        (ownedTechs.getSize() + newTechs.getSize()) * 1 +
                        (ownedUnits.getSize() + newUnits.getSize()) + 3;

		Data[] savedRessources = new Data[totalSize];
		int currentIndex = 0;
		
		for (int i = 0; i < 9; i++)
		{
			savedRessources[currentIndex]  = new Data(myRessources[i]);
			currentIndex++;
		}
		
		savedRessources[currentIndex] = new Data(ownedStructures.getSize() + newStructures.getSize());
		currentIndex++;
		for (int i = 0; i < ownedStructures.getSize(); i++)
		{
			savedRessources[currentIndex] = new Data(((Ressource) ownedStructures.get(i)).getId());
			currentIndex++;
			savedRessources[currentIndex] = new Data(((Structure) ownedStructures.get(i)).getActive() == true ? 1 : 0);
			currentIndex++;
		}

		for (int i = 0; i < newStructures.getSize(); i++)
		{
			savedRessources[currentIndex] = new Data(((Ressource) newStructures.get(i)).getId());
			currentIndex++;
			savedRessources[currentIndex] = new Data(((Structure) newStructures.get(i)).getActive() == true ? 1 : 0);
			currentIndex++;
		}

		savedRessources[currentIndex] = new Data(ownedTechs.getSize() + newTechs.getSize());
		currentIndex++;

		for (int i = 0; i < ownedTechs.getSize(); i++)
		{
			savedRessources[currentIndex] = new Data(((Ressource) ownedTechs.get(i)).getId());
			currentIndex++;
		}

		for (int i = 0; i < newTechs.getSize(); i++)
		{
			savedRessources[currentIndex] = new Data(((Ressource) newTechs.get(i)).getId());
			currentIndex++;
		}

		savedRessources[currentIndex] = new Data(ownedUnits.getSize() + newUnits.getSize());
		currentIndex++;

		for (int i = 0; i < ownedUnits.getSize(); i++)
		{
			savedRessources[currentIndex] = new Data(((Ressource) ownedUnits.get(i)).getId());
			currentIndex++;
		}

		for (int i = 0; i < newUnits.getSize(); i++)
		{
			savedRessources[currentIndex] = new Data(((Ressource) newUnits.get(i)).getId());
			currentIndex++;
		}

		return savedRessources;
	}
	
	public void setAllPlayerRessources(Data[] loadedRessources, int offset) throws Exception {
		int currentIndex = offset;
		
		ownedRessources.clear();
		ownedStructures.clear();
		newStructures.clear();
		ownedTechs.clear();
		newTechs.clear();
		ownedUnits.clear();
		newUnits.clear();
		
		for (int i = 0; i < 9; i++)
		{
			myRessources[i] = Integer.parseInt(loadedRessources[currentIndex].getData());
			currentIndex++;
		}
		
		int ownedSize = Integer.parseInt(loadedRessources[currentIndex].getData());
		currentIndex++;
		for (int i = 0; i < ownedSize; i++)
		{
			Structure newRessource = (Structure) (numberTemplates.get(Integer.parseInt(loadedRessources[currentIndex].getData())).copy());
			currentIndex++;
			newRessource.setActive(Integer.parseInt(loadedRessources[currentIndex].getData()) == 1 ? true : false);
			currentIndex++;
			ownedStructures.addElement(newRessource);
			ownedRessources.add(newRessource);
		}

		ownedSize = Integer.parseInt(loadedRessources[currentIndex].getData());
		currentIndex++;
		for (int i = 0; i < ownedSize; i++)
		{
			Tech newRessource = (Tech) (numberTemplates.get(Integer.parseInt(loadedRessources[currentIndex].getData())).copy());
			currentIndex++;
			ownedTechs.addElement(newRessource);
			ownedRessources.add(newRessource);
		}
		
		ownedSize = Integer.parseInt(loadedRessources[currentIndex].getData());
		currentIndex++;
		for (int i = 0; i < ownedSize; i++)
		{
			Unit newRessource = (Unit) (numberTemplates.get(Integer.parseInt(loadedRessources[currentIndex].getData())).copy());
			currentIndex++;
			ownedUnits.addElement(newRessource);
			ownedRessources.add(newRessource);
		}
		
		update();
	}
	
	public void addListener(Observer o)
	{
		listeners.add(o);
	}
	
	public void notifyObservers()
	{
	    for (Observer o : listeners)
	    	o.notifyMe();
	}

	public int[] getPlayerRessources() {
		return myRessources;
	}
	
	public int[] getStructureUpkeep() {
		int[] res = {0,0,0,0,0,0,0,0,0};
		
		for (int i = 0; i < ownedStructures.getSize(); i++)
		{
			Structure s =  (Structure) ownedStructures.get(i);
			if (s.getActive())
				for (int j = 0; j < 9; j++)
					res[j] += s.getUpkeep()[j];
		}
		
		for (int i = 0; i < newStructures.getSize(); i++)
		{
			Structure s =  (Structure) newStructures.get(i);
			if (s.getActive())
				for (int j = 0; j < 9; j++)
					res[j] += s.getUpkeep()[j];
		}	
		
		return res;
	}
	
	public int[] getUnitUpkeep() {
        int[] res = {0,0,0,0,0,0,0,0,0};
		
		for (int i = 0; i < ownedUnits.getSize(); i++)
		{
			Unit u =  (Unit) ownedUnits.get(i);
			for (int j = 0; j < 9; j++)
				res[j] += u.getUpkeep()[j];
		}
		
		for (int i = 0; i < newUnits.getSize(); i++)
		{
			Unit u =  (Unit) newUnits.get(i);
		    for (int j = 0; j < 9; j++)
				res[j] += u.getUpkeep()[j];
		}
		
		return res;
	}
	
	public int[] getProduction() {
        int[] res = {0,0,0,0,0,0,0,0,0};
		
		for (int i = 0; i < ownedStructures.getSize(); i++)
		{
			Structure s =  (Structure) ownedStructures.get(i);
			if (s.getActive())
				for (int j = 0; j < 9; j++)
					res[j] += s.getOutput()[j];
		}
		
		for (int i = 0; i < newStructures.getSize(); i++)
		{
			Structure s =  (Structure) newStructures.get(i);
			if (s.getActive())
				for (int j = 0; j < 9; j++)
					res[j] += s.getOutput()[j];
		}	
		
		return res;
	}
}